/*
 *
 *	(GNU GPL) kobey
 *	本测试用例，主要用来探索一个Linux进程环境变量以及参数的存储、申请和释放过程
 *	1，在我们的glibc库中已经包括了一个进程环境变量的一个指针数组，我们可以通过extern申明
 *		就可以使用
 *	2，打印出来一个Linux进程的环境的变量之后，可以通过老方法cat /proc/pid/maps比较
 *		发现我们的环境变量的保存地址以及后续更改环境变量后分配内存和释放情况	
 *	
 *	3，在进程没有运行之前修改环境变量
 *		这样没有任何问题，而且环境变量存储在栈的顶部，与栈共享一个连续的虚拟地址空间
 *		在更进入函数体的时候，理论上来说，此刻没有使用任何栈段空间，但是其实，栈顶已经
 *		使用了2个物理页，因为它就是用来保存环境变量的字符串和命令行参数。
 *
 *	4，在进程运行期间，新增环境变量
 *		1）首先在堆中申请一块内存用来保存因为新增环境变量引起的指针数组的地址的变化，
 *			也就是新增后，首先改变了保存指针数组的地址，在堆中开辟一块内存用来保存
 *			请注意，这个时候原来栈顶的内存的分布依然存在，只是就这么浪费掉了
 *		2）然后再从堆中开辟一块内存用来存放新增的环境变量
 *
 *	5，在进程运行期间，修改环境变量
 *		会从堆中开辟一块内存，用来存放修改后的环境变量，然后更新数组指针中对应字符串的指针
 *
 *	6，总结
 *
 *		1）环境变量的存储在栈顶，而且编译的时候就固定分配大小
 *		2）如果在程序运行期间，任何修改环境变量的动作都会在堆空间中分配内存，如果新增，还
 *			需要修改环境变量数组的指针
 *		3）在堆中分配的环境变量内存，是不会释放的，所以，可以理解为，这是一个内存泄露问题
 *
 *		4）优化问题
 *			非常简单，程序运行后，应该尽量不要再修改任何环境变量	
 *		
 *
 *
 *
 *
 *
 *
 * */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
extern char **environ;

int main()
{
	char **env = environ;
	printf("environ:%p\n", environ);//打印环境变量指针的地址
	while(*env) {
		printf("env:%p\t%p\t%s\n", env, *env, *env);
		env++;
	}

	printf("\n#######################set env######################\n\n");
	/*新增一个环境变量*/
	setenv("kobey", "hello", 1 );

	env = environ;
        printf("environ:%p\n", environ);
        while(*env) {
                printf("env:%p\t%p\t%s\n", env, *env, *env);
                env++;
        }

	/*修改一个环境变量*/

	envset("PATCH", "kobey", 1);
	printf("environ:%p\n", environ);//打印环境变量指针的地址
        while(*env) {
                printf("env:%p\t%p\t%s\n", env, *env, *env);
                env++;
        }

	pause();
	return 0;
}
